﻿#region Copyright (c) 2009 S. van Deursen
/* The CuttingEdge.EntitySorting library.
 * 
 * To contact me, please visit my blog at http://www.cuttingedge.it/blogs/steven/ 
 *
 * Copyright (c) 2009 S. van Deursen
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
 * associated documentation files (the "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the
 * following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all copies or substantial
 * portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 * LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
 * EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
 * USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#endregion

using System;
using System.Linq;
using System.Linq.Expressions;

using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace CuttingEdge.ServiceLayerHelpers.Tests.Unit
{
    [TestClass]
    public class EntitySorterExtensionsTests
    {
        private readonly IEntitySorter<Person> validEntitySorter = new ValidPersonEntitySorter();
        private readonly Expression<Func<Person, int>> validKeySelector = p => p.Id;
        private readonly string validPropertyName = "Id";

        [TestMethod]
        public void OrderBy_WithValidArguments_ReturnsAValue()
        {
            // Act
            var sorter = EntitySorterExtensions.OrderBy(this.validEntitySorter, this.validKeySelector);

            // Assert
            Assert.IsNotNull(sorter);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void OrderBy_WithNullBaseSorter_ThrowsException()
        {
            EntitySorterExtensions.OrderBy(null, this.validKeySelector);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void OrderBy_WithNullLambda_ThrowsException()
        {
            // Arrange
            Expression<Func<Person, int>> invalidKeySelector = null;

            // Act
            EntitySorterExtensions.OrderBy(this.validEntitySorter, invalidKeySelector);
        }

        [TestMethod]
        public void OrderByDescending_WithValidArguments_ReturnsAValue()
        {
            // Act
            var sorter = 
                EntitySorterExtensions.OrderByDescending(this.validEntitySorter, this.validKeySelector);

            // Assert
            Assert.IsNotNull(sorter);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void OrderByDescending_WithNullBaseSorter_ThrowsException()
        {
            EntitySorterExtensions.OrderByDescending(null, this.validKeySelector);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void OrderByDescending_WithNullLambda_ThrowsException()
        {
            // Arrange
            Expression<Func<Person, int>> invalidKeySelector = null;

            // Act
            EntitySorterExtensions.OrderByDescending(this.validEntitySorter, invalidKeySelector);
        }

        [TestMethod]
        public void ThenByKeySelector_WithValidArguments_ReturnsAValue()
        {
            // Act
            var sorter = EntitySorterExtensions.ThenBy(this.validEntitySorter, this.validKeySelector);

            // Assert
            Assert.IsNotNull(sorter);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void ThenByKeySelector_WithNullBaseSorter_ThrowsException()
        {
            // Arrange
            IEntitySorter<Person> invalidSorter = null;

            // Act
            EntitySorterExtensions.ThenBy(invalidSorter, this.validKeySelector);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void ThenByKeySelector_WithNullLambda_ThrowsException()
        {
            // Arrange
            Expression<Func<Person, int>> invalidExpression = null;

            // Act
            EntitySorterExtensions.ThenBy(this.validEntitySorter, invalidExpression);
        }

        [TestMethod]
        public void ThenByDescendingKeySelector_WithValidArguments_ReturnsAValue()
        {
            // Act
            var sorter = 
                EntitySorterExtensions.ThenByDescending(this.validEntitySorter, this.validKeySelector);

            // Assert
            Assert.IsNotNull(sorter);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void ThenByDescendingKeySelector_WithNullBaseSorter_ThrowsException()
        {
            EntitySorterExtensions.ThenByDescending(null, this.validKeySelector);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void ThenByDescendingKeySelector_WithNullLambda_ThrowsException()
        {
            // Arrange
            Expression<Func<Person, int>> invalidExpression = null;

            // Act
            EntitySorterExtensions.ThenByDescending(this.validEntitySorter, invalidExpression);
        }

        [TestMethod]
        public void ThenByPropertyName_WithValidArguments_ReturnsAValue()
        {
            // Act
            var sorter = EntitySorterExtensions.ThenBy(this.validEntitySorter, this.validPropertyName);

            // Assert
            Assert.IsNotNull(sorter);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void ThenByPropertyName_WithNullBaseSorter_ThrowsException()
        {
            EntitySorterExtensions.ThenBy<Person>(null, this.validPropertyName);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void ThenByPropertyName_WithNullPropertyName_ThrowsException()
        {
            // Arrange
            string invalidPropertyName = null;

            // Act
            EntitySorterExtensions.ThenBy(this.validEntitySorter, invalidPropertyName);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void ThenByPropertyName_WithEmptyPropertyName_ThrowsException()
        {
            // Arrange
            string invalidPropertyName = string.Empty;

            // Act
            EntitySorterExtensions.ThenBy(this.validEntitySorter, invalidPropertyName);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void ThenByPropertyName_WithInvalidPropertyName_ThrowsException()
        {
            // Arrange
            string invalidPropertyName = "Address.NonExistingProperty";

            // Act
            EntitySorterExtensions.ThenBy(this.validEntitySorter, invalidPropertyName);
        }

        [TestMethod]
        public void ThenByDescendingPropertyName_WithValidArguments_ReturnsAValue()
        {
            // Act
            var sorter = 
                EntitySorterExtensions.ThenByDescending(this.validEntitySorter, this.validPropertyName);

            // Assert
            Assert.IsNotNull(sorter);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void ThenByDescendingPropertyName_WithNullBaseSorter_ThrowsException()
        {
            EntitySorterExtensions.ThenByDescending<Person>(null, this.validPropertyName);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentNullException))]
        public void ThenByDescendingPropertyName_WithNullPropertyName_ThrowsException()
        {
            // Arrange
            string invalidPropertyName = null;

            // Act
            EntitySorterExtensions.ThenByDescending(this.validEntitySorter, invalidPropertyName);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void ThenByDescendingPropertyName_WithEmptyPropertyName_ThrowsException()
        {
            // Arrange
            string invalidPropertyName = string.Empty;

            // Act
            EntitySorterExtensions.ThenByDescending(this.validEntitySorter, invalidPropertyName);
        }

        [TestMethod]
        [ExpectedException(typeof(ArgumentException))]
        public void ThenByDescendingPropertyName_WithInvalidPropertyName_ThrowsException()
        {
            // Arrange
            string invalidPropertyName = "Address.NonExistingProperty";

            // Act
            EntitySorterExtensions.ThenByDescending(this.validEntitySorter, invalidPropertyName);
        }

        private sealed class ValidPersonEntitySorter : IEntitySorter<Person>
        {
            public IOrderedQueryable<Person> Sort(IQueryable<Person> collection)
            {
                return collection.OrderBy(p => p.Id);
            }
        }
    }
}